<?php
/*
 UTILS_ADMIN.PHP by martin $ 2010/01/12 06:02:51
*/

if(PHP_VERSION >= '5.1.0') date_default_timezone_set(TIMEZONE);

                            /**********************************************
                                         ユーティリティー関数群 for ADMIN
                            ***********************************************/
function catch_data($moby=FALSE, $author='', $title='', $com='', $extended='', $ontime='', $_category='', $comment=0, $ping=0, $index='', $tid=''){
 global $mb, $mode, $timeout, $SESSION, $DIVISION;
 $timestamp = time();
 $db = DB.'images.db';
 $mode = $tid == '' ? $mode : 'delete';
 $images_cache = is_file($db) ? file($db) : array();
 $mod_imgCache = FALSE; // 画像DBの修正flag
 $mod_mediaCache = FALSE; // MediaDBの修正flag
 $_imgs_list = p_('imgs_list') != '' ? explode(',', p_('imgs_list', 0)) : array();
 $_media_list = p_('media_list') != '' ? explode(',', p_('media_list', 0)) : array();
 $allowComment = p_('allow-comment') == 1 ? 1 : $comment;
 $allowPing = p_('allow-ping') == 1 ? 1 : $ping;
 $excerpt = ($exp=p_('excerpt')) != '' ? $exp : '';
 $category = $_category == '' ? p_('category', 2) : $_category;
 if(!isset($timeout)) $timeout = FALSE;
 $autopost = p_('type') == 'autopost' ? TRUE : FALSE;
 $autoposted = p_('autoposted') == 1 ? TRUE : FALSE;
 if($autoposted && $mode=='submit') $mode = 'update';
 $time = date('Y/m/d H:i:s');
 $pm_title = p_('pm_title') != '' ? preg_replace('{\s}', '-', p_('pm_title')) : '';
 $send_ping = p_('xmlrpc_ping') != '' ? 1 : 0;
 if(!$moby && $ontime==''){
  $author = p_('author');
  $title = p_('title');
  $title = ($title=='') ? 'タイトルなし' : $title;
  $draft = array_key_exists('draft', $_POST) ? TRUE : FALSE;
  if(p_('com')) $com = p_('com', 1); # semi-filtered data
  if($autopost && trim($com)=='') exit("No data");
  $tags = p_('tags') ? explode(',', preg_replace(array('{([^&])&#44;[\s]+}', '{&#44;[\s]*$}'), array('$1,', ''), p_('tags'))) : array();
  if(!empty($tags)) $tags = array_unique($tags);
  if($mode != 'delete'){
   if($com==''){
    page_back();
    return $DIVISION['body'] = '内容は空白ではいけません。';
   }
  }
  $extended = '';
  if(is_array(p_('extended'))){
   foreach (p_('extended', 1) as $i=>$ext){
    $comma = ($i==0) ? '' : ',';
    $extended .= $comma.$ext;
   }
  }
 } else { # via moby
  $draft = FALSE;
 }
 $id = $tid == '' ? p_('UID') : $tid;
 $new_id = -1;
 if(p_('mod_date') != ''){ // 時刻の修正時
  $_Y = $mb ? sprintf('%04d', mb_convert_kana(p_('Y'), "n", ENCODE)) : sprintf('%04d', p_('Y'));
  $_m = $mb ? sprintf('%02d', mb_convert_kana(p_('m'), "n", ENCODE)) : sprintf('%02d', p_('m'));
  $_d = $mb ? sprintf('%02d', mb_convert_kana(p_('d'), "n", ENCODE)) : sprintf("%02d", p_('d'));
  $_H = $mb ? sprintf('%02d', mb_convert_kana(p_('H'), "n", ENCODE)) : sprintf('%02d', p_('H'));
  $_i = $mb ? sprintf('%02d', mb_convert_kana(p_('i'), "n", ENCODE)) : sprintf('%02d', p_('i'));
  $_s = $mb ? sprintf('%02d', mb_convert_kana(p_('s'), "n", ENCODE)) : sprintf('%02d', p_('s'));
  $new_id = strtotime($_Y.'-'.$_m.'-'.$_d.' '.$_H.':'.$_i.':'.$_s);
  $candidate = file(log_($new_id));
  if(!empty($candidate)) $candidate = preg_grep("/^${new_id}d?\|/", $candidate);
  if(!empty($candidate)){
   page_back(2000);
   return $DIVISION['header'] .= '<p class="alert">同一時刻の記事が既にあるようです。別の時刻に変えて下さい。</p>';
  }
 }
 $_ontime = p_('ontime') != '' ? TRUE : FALSE;
 $draft = (($_ontime && !$ontime) || p_('draft') != '') ? TRUE : FALSE;
 $_id = ($new_id > 0 ) ? $new_id.($draft?'d':'') : str_replace('d','',$id).($draft?'d':''); # final id
 $__id = str_replace('d', '', $_id);
 if($_ontime){ # オンタイム
  if(!is_file($ontime_ini = OD.'ontime.ini.php')) rewrite_ini($ontime_ini, '', '$ONTIME_LIST');
  include($ontime_ini);
  foreach ($ONTIME_LIST as $i => $uid){
   if(strstr($id, $uid)){ $hit = $i; break;}
  }
  if(isset($hit)) $ONTIME_LIST[$hit] = $__id.'|'.$send_ping; else $ONTIME_LIST[] = $__id.'|'.$send_ping;
  rewrite_ini($ontime_ini, $ONTIME_LIST);
 }
 if($ontime != '' && is_numeric($ontime)){ # オンタイム
  $id = $ontime.'d'; $_id = $__id = $ontime;
 }
  
 if(MODE_STATIC){
  if($pm_title != '' && preg_match('{^[a-z0-9\-_]+$}i', $pm_title)){
   $hits = preg_grep('{,'.$pm_title.'}', file(log_($__id)));
   if(empty($hits) || (!empty($hits) && sizeof($hits) === 1) ){
    $title = $title.','.$pm_title;
    $valid_pm_title = $title;
   }
   $pm_link = date('Ym', $__id).'-'.$pm_title.EXT_STATIC;
  } else $pm_link = $_id.EXT_STATIC;
 } else $pm_link = 'index.php?UID='.$_id;
 # タグ処理
 include_once ($tagslist=OD.'tags.ini.php');
 $tags_bak = my_glob('tags.ini', DB);
 sort($tags_bak, SORT_NUMERIC);
 if(sizeof($tags_bak) < 5){
  @copy(PATH.$tagslist, PATH.DB.'tags.ini.php_'.date('Ymd_His').'.bak');
 } else {
  unlink(PATH.$tags_bak[0]);
  @copy(PATH.$tagslist, PATH.DB.'tags.ini.php_'.date('Ymd_His').'.bak');
 }
 unset($tags_bak);
 if(isset($TAGS_LIST)){
  if($draft){
   $TAGS_LIST = str_replace($__id, $_id, $TAGS_LIST);
   $TAGS_LIST = str_replace('dd', 'd', $TAGS_LIST);
  } else $TAGS_LIST = str_replace($id, $_id, $TAGS_LIST);
  if($new_id > 0) $TAGS_LIST = str_replace(array($id.'d', $id), $_id, $TAGS_LIST);
  $_TAGS_LIST = array();
  if(!empty($tags)){
   foreach ($tags as $tag){
    $match = FALSE;
    foreach ($TAGS_LIST as $i => $list){
     list($_tag, $ids) = explode('|', $list);
     if($tag == $_tag){
      $match = TRUE;
      if(!strstr($ids, $_id)) $TAGS_LIST[$i] = trim($list).",$_id";
     } else {
      if(strstr($ids, $_id) && !in_array($_tag, $tags)) $TAGS_LIST[$i] = str_replace(array(",$_id", "$_id,", $_id), '', $TAGS_LIST[$i]);
     }
    }
    if(!$match) array_unshift($TAGS_LIST, "$tag|$_id");
   }
  } else {
   $TAGS_LIST = preg_replace("{,?$_id}", "", $TAGS_LIST);
  }
  foreach ($TAGS_LIST as $_tag){
   $ps = explode('|', $_tag);
   if(empty($ps[0]) || empty($ps[1])) continue;
   $_TAGS_LIST[] = $_tag;
  }
  unset($match, $tags, $TAGS_LIST);
  $_TAGS_LIST = preg_replace(array('{,,(?!\d+?)}', '{,$}'), '', $_TAGS_LIST);
  $_TAGS_LIST = mb_str_replace(array("|,", ',,'), array('|', ','), $_TAGS_LIST);
  rewrite_ini($tagslist, $_TAGS_LIST);
 } #tag-section end
 
 $com = str_replace("/$id".'_', "/${_id}_", $com);
 $extended = str_replace("/$id".'_', "/${_id}_", $extended);
 $com = str_replace(":$id".'_', ":${_id}_", $com);
 $extended = str_replace(":$id".'_', ":${_id}_", $extended);
 
 preg_match_all('{<img src="(PIX/.+?)" .+?/>}', $com.$extended, $imgs_list); $imgs_list = $imgs_list[1];
 preg_match_all('{\[(?:media|mov):(.+?):.+?\]}', $com.$extended, $media_list); $media_list = $media_list[1];

 $newTarget = log_($__id);
 if(is_file(PATH.$newTarget)){
  $newLINES = file($newTarget);
  if($mode=='submit' && !$autoposted){
   if(!empty($newLINES) && preg_match("/${__id}d?\|/", $newLINES[0])){
    page_back();
    return $DIVISION['body'] = '<p class="alert">重複投稿です！</p>'.NL;
   }
  }
 }

 if($mode=='update' || $mode=='delete' || array_key_exists('do_delete',$_POST) || is_numeric($ontime)){
  $orgTarget = log_($id);
  $orgLINES = file($orgTarget); // 元のターゲットログ
  $isAnotherLog = ($orgTarget!=log_($__id)) ? 1 : 0;
 }
 if($id != $_id || !$draft){
  $DIRS = array(IMG_DIR, IMG_DIR.THUMB1, IMG_DIR.THUMB2, AFFIXED_DIR, MEDIA_DIR);
  foreach ($DIRS as $dir) rename_upfile($id, $_id, $dir);
  $images_cache = preg_replace('{^'.$id.'\|}', $_id.'|', $images_cache);
  $mod_imgCache = TRUE;
 }

 // 新規投稿時の添付画像(via upload | imager) の処理: キャッシュ作成
 if(($mode=='submit' || ($mode=='update' && $autopost)) && !empty($imgs_list)){
  foreach ($imgs_list as $img){
   foreach ($images_cache as $n=>$I){
    list($cid,,$cname,) = explode('|', $I);
    if(basename($img)==$cid.'_'.$cname){
     $parts = explode('|', $I);
     $parts[0] = $_id; $parts[6] = $category;
     $parts[7] = $title;
     $images_cache[$n] = implode('|', $parts);
     $mod_imgCache = TRUE;
     break;
    }
   } # foreach
  } # foreach
 }

 // 編集時の添付画像の処理: キャッシュ作成
 if($mode=='update' || $mode=='delete' || is_numeric($ontime)){
  if( $mode=='update' && (strpos($id, 'd') && !$draft) || (!strpos($id, 'd') && $draft) ){
   $images_cache = preg_replace('{^'.$id.'\|}', $_id.'|', $images_cache);
   $mod_imgCache = TRUE;
  } else {
   $imgs_unlinked = array_diff($_imgs_list, $imgs_list);
   $imgs_linked = array_diff($imgs_list, $_imgs_list);
   if(!empty($imgs_unlinked)){
    foreach ($imgs_unlinked as $img){
     foreach ($images_cache as $n=>$I){
      list($cid,,$cname,) = explode('|', $I);
      if(($bn=basename($img))==$cid.'_'.$cname){
       $parts = explode('|', $I); $to = $parts[1].'_'.$cname;
       if(is_file($img)) rename($img, IMG_DIR.$to);
       if(is_file(IMG_DIR.THUMB1.$bn) && !is_file(IMG_DIR.THUMB1.$to)) rename(IMG_DIR.THUMB1.$bn, IMG_DIR.THUMB1.$to);
       if(is_file(IMG_DIR.THUMB2.$bn) && !is_file(IMG_DIR.THUMB2.$to)) rename(IMG_DIR.THUMB2.$bn, IMG_DIR.THUMB2.$to);
       $parts[0] = $parts[1]; $parts[6] = $parts[7] = '';
       $images_cache[$n] = implode('|', $parts);
       $mod_imgCache = TRUE;
       break;
      }
     } # foreach
    } # foreach
   }
   if(!empty($imgs_linked)){
    foreach ($imgs_linked as $img){
     foreach ($images_cache as $n=>$I){
      list($cid,,$cname,) = explode('|', $I);
      if(($bn=basename($img))==$cid.'_'.$cname){
       $parts = explode('|', $I);
       $parts[0] = $_id; $parts[6] = $category;
       $parts[7] = $title;
       $images_cache[$n] = implode('|', $parts);
       $mod_imgCache = TRUE;
       break;
      }
     } # foreach
    } # foreach
   }
  } # else
 } # update

 # ログのフォーマット
 $logFormat = $_id.'|'.$category.'|'.$title.'|'.$com.'|'.$author.'|'.$allowComment.'|'.$allowPing.'|'.$excerpt.'|'.$extended.'|'.NL;

 if(!$moby && $mode != 'delete' && ($_id == '' || $category == '' || $title == '' || $com == '' || $author == '')) return;
 if(p_('send_ping_auto')==1){ // do auto-trackback
  $links = get_links(autolink($com));
  $tb_uris = array();
  if(!empty($links)){
   foreach ($links as $link){
    $tb_uris = array_merge($tb_uris, my_auto_discovery($link));
   }
  }
  foreach ($tb_uris as $tb_uri) cast_ping_data($com, $tb_uri);
 }
 if(!$timeout && p_('send_ping_manu')==1){ // manual trackback
  if(strpos($_id, 'd')){
   $DIVISION['body'] .= '<p class="alert center" style="margin-top:15px;">未公開なのでトラックバックPINGは打ちませんでした.</p>';
  } else cast_ping_data($com);
 }
 if(!$timeout && $send_ping == 1){ // send update ping
  if(!strpos($_id, 'd')){
   include('xmlrpc.php');
   $ping_result = send_ping_xmlrpc(BLOG_NAME, ROOT_PATH.'index.php');
  } else {
   $ping_result = '';
   $DIVISION['body'] .= '<p class="alert center" style="margin-top:15px;">ドラフト投稿なので更新PINGは打ちませんでした。'
                     .($_ontime ? '<br/>ただしオンタイム投稿時間が成功したら更新PINGを送ります。' : '').'</p>';
  }
 } else $ping_result = '';
 if($mode=="submit"){  # 新規に書き庫
  if(is_numeric($ontime)){
   $newLINES[$index] = $logFormat;
  } else $newLINES[] = $logFormat;
  usort($newLINES, 'SORT_BY_DATE'); // 日付の新しい順に
  rewrite($newTarget, $newLINES);
 } 

 if($mode=='update' || is_numeric($ontime)){  # 編集後
  $index = get_article_index($id, $orgLINES);
  if($new_id==-1){ // 日付の修正なしなら
   $orgLINES[$index] = $logFormat; // もとのログを新たに入れ替え
   usort($orgLINES, 'SORT_BY_DATE');
   rewrite($orgTarget, $orgLINES);
  } else {                 // 日付の修正ありなら
   array_splice($orgLINES, $index, 1);// $idの配列要素をカット
   // トラックバックのIDも変更
   $ori_tb = my_glob("$id", TB_DIR);
   if(!empty($ori_tb)){
    $new_tb = preg_replace("/(\d{9,})([^\d]+)/", "$new_id$2", $ori_tb[0]);
    rename($ori_tb[0], $new_tb); 
   }
   // コメントログのIDも変更
   $ori_cmt = my_glob("$id", CMT_DIR);
   if(isset($ori_cmt[0])){
    $new_cmt = preg_replace("{(\d{9,})([^\d]+)}", "$new_id$2", $ori_cmt[0]);
    $lines = file($ori_cmt[0]);
    array_splice($lines, 0, 1, preg_replace("{^$id}", $new_id, $lines[0]));
    rewrite($ori_cmt[0], $lines);
    rename($ori_cmt[0], $new_cmt);
   }
   if($isAnotherLog){ // ログファイルが別
    $newLINES[] = $logFormat;
    usort($newLINES, 'SORT_BY_DATE');
    rewrite($orgTarget, $orgLINES);
    rewrite($newTarget, $newLINES);
   } else {           // ログファイルが同じ
    $orgLINES[] = $logFormat;
    usort($orgLINES, 'SORT_BY_DATE');
    rewrite($orgTarget, $orgLINES);
   }
  }
  $cmt = my_glob("$_id", CMT_DIR);
  if(isset($cmt[0])){
   $cmt_lines = file($cmt[0]);
   list(,$cat,$_title,$no,$num) = explode('|', $cmt_lines[0]);
   if($title != $_title || $cat != $category){
    $cmt_lines[0] = "$_id|$category|".(isset($valid_pm_title) ? $valid_pm_title : $title)."|$no|$num".NL;
    rewrite($cmt[0], $cmt_lines);
   }
  }
 }                                     # end $mode==update

 if($mode=='update' || $mode=='submit' || is_numeric($ontime)){
  if(RSS2){
   include_once('modules/rss2.0.inc.php');
   createRSS20($timestamp);
  }

  if(ATOM10){
   include_once('modules/atom1.0.inc.php');
   createATOM10($timestamp);
  }
  update_cache(array('recently', 'category', 'articles_volume', 'recent_trackbacks', 'recent_comments', 'tags'), $_id);
  if($mod_imgCache) update_images_cache($images_cache);
  if(MODE_STATIC && !WITH_DATE){
   include_once(OD.'idtitle');
   array_unshift($IDTITLE, "$_id\t$pm_title");
   rewrite_ini(OD.'idtitle', $IDTITLE);
  }
  if(is_numeric($ontime) && trim(MAILTO) != ''){ # オンタイム投稿の完了メール
   include_once('modules/mail.inc.php');
   $inform = '以下のエントリーを'.date('Y-m-d H:i:s', $timestamp).'にオンタイム投稿しました。'.NL.NL.str_replace('|', NL, $logFormat);
   send_jp_mail('オンタイム投稿完了', $inform, '', MAILTO);
   return;
  }
  $msg = $mode=='submit' ? '新規'.($draft ? (!$_ontime ? 'ドラフト' : 'オンタイム') :'').'投稿' : ($draft ? (!$_ontime ? 'ドラフト' : 'オンタイム') :'').'更 新';

  if(trim(MAILTO) != '' && isUserLoggedIn()){ # ユーザーのエントリーは管理者にメールする
   include_once('modules/mail.inc.php');
   $inform = 'ユーザーの'.$author.'さんが'.$msg.'したようです。以下ログ形式で。'.NL.NL.str_replace('|', NL, $logFormat);
   send_jp_mail('ppBlogユーザーによる投稿・編集', $inform, '', MAILTO);
  }
  if(!$moby){
   if($autopost){ // via AJAX
    rename_upfile($id, $_id, AFFIXED_DIR);
    exit($time);
   } else if(p_('xmlrpc_ping')==1 || p_('send_ping_manu')==1){
    $DIVISION['body'] .= '<h4 class="center" style="margin-top:100px;font-weight:500;font-size:107%;">'.$msg.' 完 了！'
                      .  '<p style="margin-top: 1em;">[<a href="'.$pm_link.'">記事を確認する</a>]</p></h4>';
   } else {
    //refresh_page((strpos($_id, 'd') ? "admin.php?mode=edit&UID=$_id" : "index.php?UID=$_id"), $timeout ? 3000 : 1500);
    refresh_page($pm_link, $timeout ? 3000 : 1500);
    $DIVISION['body'] .= '<h4 class="center" style="margin-top:105px;font-weight:500;font-size:107%;">'.$msg.' 完 了！ <br />ページを更新します。</h4>';
   }
   if($timeout==TRUE){
    $DIVISION['body'] .= '<p class="alert">タイムアウトしていましたが，再度ログインして投稿処理を続けました.</p>';
   }
   return $DIVISION['body'] .= $ping_result;
  }
 }
 if($mode=="delete" || array_key_exists('do_delete', $_POST) || $tid != ''){
  $id = substr($id, 0, 10);
  if($mod_imgCache){
   $images_cache = preg_replace("/^(${id}d?)(\|\d+?\|.+?\|\d+?\|\d+?\|.+?\|)(.+?\|.+?\|)(.+$)/se",
   "substr('\\1',0,10).'\\2||'.'\\4'", $images_cache);
   update_images_cache($images_cache);
  }
  if(!empty($orgLINES)){
   $tindex = get_article_index($id, $orgLINES);
   list(,,,$_com,,,,,$_extended) = explode('|', $orgLINES[$tindex]);
   array_splice($orgLINES, $tindex, 1);// $idの配列要素をカット
   rewrite($orgTarget, $orgLINES);
   $ce = $_com.$_extended;
  }
  if($ce != '' && preg_match_all('/\[file:([^\/]+)\/\]/i', $ce, $attached_files)){ // 余分添付ファイルも削除
   foreach($attached_files[1] as $af) if(is_file(PATH.$af)) @unlink(PATH.$af);
  }
  $ori_cmt = my_glob("$id", CMT_DIR);
  if(!empty($ori_cmt[0])){
   unlink($ori_cmt[0]); # コメントログ削除
  }
  if(RSS2){
   include_once('modules/rss2.0.inc.php');
   createRSS20($timestamp);
  }
  if(ATOM10){
   include_once('modules/atom1.0.inc.php');
   createATOM10($timestamp);
  }
  if($tid == '') update_cache(array('recently', 'recent_comments', 'recent_trackbacks', 'category', 'articles_volume', 'tags'), $id);
  if(!$moby){
   if($tid == ''){
    refresh_page('admin.php?mode=article');
    $DIVISION['body'] .= '<p class="alert" style="margin-top:35px;">選択した記事を削除しました</p>';
   }
  }
 } # delete
 unset($orgLINES, $images_cache);
}

function replace_log_by_target($target='', $replace='', $dir=LOG){ # 全ログ中のターゲット要素を置換
 global $LOGS;
 if($target=='') return;
 $LOGS = $dir==LOG ? $LOGS : my_glob(EXT, $dir);
 foreach($LOGS as $log){
  $fp = @fopen($log, "rb");
  $mod = 0;
  $LINES = array();
  if($fp){
   while(!feof($fp)){
    $line = fgets($fp);
    if(trim($line)=='') continue;
    if($line && substr($line, -2) != '|'.NL) $line .= fgets($fp);
    if(strpos($line, $target)){
     $LINES[] = rtrim(my_str_replace($target, $replace, $line));
     $mod = 1;
    } else $LINES[] = rtrim($line);
   } # while-loop
   fclose($fp);
  } # $fp
  if($mod) rewrite($log, $LINES);
 } # while
 unset($LINES);
}

function rename_upfile($pre, $post, $dir=''){ // 日付修正時に使用. 添付ファイルの付加IDを変える
 global $mode;
 $ori_files = my_glob("$pre", PATH.$dir);
 if(!empty($ori_files)){
  foreach ($ori_files as $file){
   rename($file, preg_replace("/${pre}d?_/", $post.'_', $file)); // ID変更
  }
 }
}

# Create Thumbnail: $w, $h is original size.
function create_thumbnail($input, $output, $w='', $h='', $ratio='', $quality=75){ // Revised in v.1.8.6
 $info = getimagesize($input);
 $w = is_numeric($w) ? $w : $info[0]; $h = is_numeric($h) ? $h : $info[1];
 if($ratio=='') $ratio = THUMB_ISIZE / max($w, $h);
 $_w  = round($w * $ratio);
 $_h = round($h * $ratio);
 // allocate appropreate memory from php.net users' contribute notes.
 if(isset($info['channels']) && $info[2] !== 1){
  $fudgeFactor = 1.8;
  $memoryNeeded = round(($info[0] * $info[1] * $info['bits'] * $info['channels'] / 8 + Pow(2, 16)) * $fudgeFactor);
  $memoryLimit = 8 * 1048576;
  if(memory_get_usage() + $memoryNeeded > $memoryLimit){
   $newLimit = ceil((memory_get_usage() + $memoryNeeded) / 1048576);
   if(substr(ini_get('memory_limit'), 0, -1) < $newLimit) ini_set('memory_limit', $newLimit.'M');
  }
 }
 switch ($info[2]){ 
  case 1 : $img_in = ImageCreateFromGIF($input); break;
  case 2 : $img_in = ImageCreateFromJPEG($input); break;
  case 3 : $img_in = ImageCreateFromPNG($input);  break;
 }
 if(!isset($img_in) || empty($img_in)){
 
  $img_out = (GD2 && $info[2] != 1) ? ImageCreateTrueColor(THUMB_ISIZE, THUMB_ISIZE) : ImageCreate(THUMB_ISIZE, THUMB_ISIZE);
  $bg = ImageColorAllocate ($img_out, 245, 245, 245);
  $tc = ImageColorAllocate ($img_out, 50, 50, 50);
  ImageFilledRectangle($img_out, 0, 0, THUMB_ISIZE, THUMB_ISIZE, $bg);
  imageRectangle($img_out, 0, 0, THUMB_ISIZE, THUMB_ISIZE, $tc);
  ImageString($img_out, 2, 10, 30, "CLICK TO SHOW", $tc);
  ImageString($img_out, 2, 8, 50, "ORIGINAL IMAGE", $tc);
  $output = OD.'error.png';
 } else $img_out = ImageCreateTrueColor($_w, $_h) or ImageCreate($_w, $_h);
 if(!empty($img_in)){
  @ImageCopyResampled($img_out, $img_in, 0, 0, 0, 0, $_w, $_h, $w, $h) or
  ImageCopyResized($img_out, $img_in, 0, 0, 0, 0, $_w, $_h, $w, $h);
 }
 switch ($info[2]) { 
  case 1 : @ImageGIF($img_out, $output);  break;
  case 2 : ImageJPEG($img_out, $output, $quality); break;
  default : ImagePNG($img_out, $output);  break;
 }
 if(!empty($img_in)) ImageDestroy($img_in);
 ImageDestroy($img_out);
}

if(!function_exists('memory_get_usage')){
 function memory_get_usage(){
  if(substr( PHP_OS, 0, 3)=='WIN'){
   $output = array();
   exec('tasklist /FI "PID eq '.getmypid().'" /FO LIST', $output);
   return preg_replace('{[\D]}', '', $output[5]) * 1024;
  } else { // UNIX presumed
   $pid = getmypid();
   exec("ps -eo%mem,rss,pid | grep $pid", $output);
   $output = explode("  ", $output[0]);
   return $output[1] * 1024;
  }
 }
}

function make_trackback_DB(){
 $tb_DB = DB.'trackback.db';
 if(file_exists($tb_DB)) unlink($tb_DB);
 mk_fl($tb_DB);
 $tb_content = get_file_content($tb_DB);
 $TBS = my_glob(EXT, TB_DIR);
 $tb_db = array();
 $TBID = preg_replace("/.*?(\d{9,}).*/","$1", $TBS);
 foreach ($TBS as $i=>$tb){
  $decoded = unserialize(get_file_content($tb));
  if(count($decoded)==0){
   unlink($tb); continue;
  }
  $tb_db[$TBID[$i]] = count($decoded);
 }
 if(!empty($tb_db)) rewrite($tb_DB, serialize($tb_db));
 unset($tb_db);
}

function mod_images_DB($images_list=array(), $mode='ADD', $type='IMG'){
 if(empty($images_list)) return;
 $db = $type=='IMG' ? DB.'images.db' : DB.'media.db';
 if(is_file($db)){
  $images_cache = file($db);
 } else $images_cache = array();

 foreach($images_list as $image){
  $images_cache = ImageCache($image, $mode, $images_cache);
  update_images_cache($images_cache, $type);
 }
}

function make_images_DB(){
 global $DIVISION;
 $chunk = 50;
 $div = '<div class="center" style="margin-top: 20%;"><img src="Images/loader.gif" alt="wait..." /></div>';
 if(($i = g_('aim')) != ''){
  list($i, $count) = explode('d', $i);

  if(is_file(DB.'images_db'.$i.'.tmp')){
   $DIVISION['body'] .= $div;
   images_DB(file(DB.'images_db'.$i.'.tmp'));
   unlink(DB.'images_db'.$i.'.tmp');
   refresh_page('admin.php?mode=rebuild&aim='.($i + 1).'d'.$count, 3000);
   return $DIVISION['body'] .= '<p class="center">画像データベース構築 '.ceil($i/ $count * 100).'% 完了</p>';
  } else {
   update_images_cache(file(DB.'images.db'));
   refresh_page('admin.php?mode=imager');
   return $DIVISION['body'] .= '<p class="alert" style="margin-top: 22%;">画像データベース構築が終了しました</p>';
  }
 } else {
  $DIVISION['body'] .= $div;
  $TMPS = my_glob("images_db", DB);
  if(empty($TMPS)){
   if(is_file(DB.'images.db')) unlink(DB.'images.db');
   $IMGS = my_glob("_", IMG_DIR);
   $size = count($IMGS);
   $TF = ceil($size / $chunk);
   for ($i = 0; $i < $TF; $i++) rewrite(DB.'images_db'.$i.'.tmp', array_slice($IMGS, $i * $chunk, $chunk));
   $TMPS = my_glob("images_db", DB);
  }
  images_DB(file(DB.'images_db0.tmp'));
  unlink(DB.'images_db0.tmp');
  refresh_page('admin.php?mode=rebuild&aim=1d'.count($TMPS), 2000);
 }
}

function images_DB($IMGS = array()){
 if(empty($IMGS)) return;
 $images_cache = array();
 foreach ($IMGS as $i => $img){
  $img = trim($img);
  list($ID,) = explode('_', $_img = basename($img), 2);
  $img_name = str_replace($ID.'_','',$_img);
  $size = getimagesize($img);
  $ratio1 = round(THUMB_ISIZE / max($size[0], $size[1]), 5);
  $ratio2 = round(MAX_ISIZE / max($size[0], $size[1]), 5);
  $logline = log_($ID)=='' ? array() : file(log_($ID));
  $title = $category = '';
  $hit = preg_grep("{^$ID}", $logline);
  $hit = reset($hit);
  if(!empty($hit)){
   list(,$category,$title,$body,,,,,$extended) = explode('|', $hit);
   if(strpos($title, ',')) list($title,) = explode(',', $title);
   if(!preg_match('{<img src="'.$img.'}', $body.$extended)){ # ID が一致しても文中で使われていない場合
    $title = $category = '';
   }
  } #hit
  unset($logline);
  $images_cache[$i] = sprintf("%010s", $ID)."|".filemtime($img)."|$img_name|$size[0]|$size[1]|".round(filesize($img)/1024,1)."|$category|$title|\t";
  if($ratio1 < 1 && GD==TRUE){
   if($size[2]!=6){ # Not BMP
    if(!is_file($thumb = IMG_DIR.THUMB1.$_img)) create_thumbnail($img, $thumb, $size[0], $size[1], $ratio1);
    if(!is_file($thumb = IMG_DIR.THUMB2.$_img) && $ratio2 < 1){
     create_thumbnail($img, $thumb, $size[0], $size[1], $ratio2);
    }
    $images_cache[$i] .= round($ratio1 * $size[0]).'|'.round($ratio1 * $size[1]).'|0|'.(($ratio2 < 1) ? round($ratio2 * $size[0]).'|'.round($ratio2 * $size[1]).'|'.NL : NL);
   } else $images_cache[$i] .= round($ratio1 * $size[0])."|".round($ratio1 * $size[1])."|BMP|\n"; // BMP
  } else {
   $images_cache[$i] .= NL; // small enough
  }
 } #foreach
 update_images_cache($images_cache, 'IMG', TRUE);
 unset($images_cache);
}

function ImageCache($imgfile='', $mode='ADD', $images_cache=array()){ // $mode = ADD | DEL
 if(!preg_match('{('.IMG_DIR.'|'.MEDIA_DIR.')\d{9,}d?_}', $imgfile) && is_file($imgfile)){
  unlink($imgfile); return;
 }
 list($id, $name) = explode('_', basename($imgfile), 2);
 
 $dir = strstr($imgfile, IMG_DIR) ? IMG_DIR : MEDIA_DIR;
 $id = sprintf('%010s', $id);

 if($mode=='ADD'){
  $logline = log_($id)=='' ? array() : file(log_($id));
  $title = $category = $body = '';
  $hit = preg_grep("{^$id}", $logline);
  $hit = reset($hit);
  unset($logline);
  if(!empty($hit)){
   list(,$category,$title,$body,,,,,$extended) = explode('|', $hit);
   $body = $body.$extended;
  } #hit
  if(strstr($imgfile, IMG_DIR)){
   if(!preg_match('{<img src="'.$imgfile.'}', $body)){ # ID が一致しても文中で使われていない場合
    $title = $category = '';
   }
   $size = getimagesize($imgfile);
   $ratio = THUMB_ISIZE / max($size[0],$size[1]);
   $_images_cache = sprintf("%010s", $id)."|".filemtime($imgfile)."|$name|$size[0]|$size[1]|".round(filesize($imgfile)/1024,1)."|$category|$title|\t";
   if($ratio < 1 && GD==TRUE){
    if($size[2]!=6){ # Not BMP
     $thumb = IMG_DIR.THUMB1.$id.'_'.$name;
     if(!is_file($thumb)) create_thumbnail($imgfile, $thumb, $size[0], $size[1], $ratio);
     $_th = getimagesize($thumb);
     $_images_cache .= "|$_th[0]|$_th[1]|".round(filesize($thumb)/1024,1)."|\n";
    } else $_images_cache .= round($ratio*$size[0])."|".round($ratio*$size[1])."|BMP|\n"; // BMP
   } else {
    $_images_cache .= NL; // small enough
   }
  } else { // MEDIA
   if(!preg_match('{\[(?:media|mov):'.str_replace(MEDIA_DIR, '', $imgfile).'.+?\]}', $body)){ # ID が一致しても文中で使われていない場合
    $title = $category = '';
   }
   $_images_cache = sprintf("%010s", $id)."|".filemtime($imgfile)."|$name|".round(filesize($imgfile)/1024,1)."|$category|$title|\n";
  }
 } #ADD
 
 if($mode=='DEL'){
  $tarIndex = preg_grep('/^'.$id.'\|\d{9,}\|'.$name.'/', $images_cache);
  $tarIndex = array_keys($tarIndex); $tarIndex = $tarIndex[0];
  if($dir==IMG_DIR){
   unlink($imgfile);
   if(strstr($imgfile, IMG_DIR)){
    if(is_file($d=str_replace(IMG_DIR,IMG_DIR.THUMB1,$imgfile))) unlink($d);
    if(is_file($d=str_replace(IMG_DIR,IMG_DIR.THUMB2,$imgfile))) unlink($d);
   }
  } else { // MEDIA
   unlink(str_replace(MEDIA_DIR.MEDIA_DIR, MEDIA_DIR, $imgfile));
  }
  array_splice($images_cache, $tarIndex, 1);                        # 削 除
 }
 return array_unique($images_cache);
}

function update_images_cache($images_cache=array(), $type='IMG', $add = FALSE){
 global $theme_dir;
 $images_linked_cache = $images_unlinked_cache = array();
 $db = $type=='IMG' ? DB.'images.db' : DB.'media.db';
 $db_linked = $type=='IMG' ? DB.'images_linked.db' : DB.'media_linked.db';
 $db_unlinked = $type=='IMG' ? DB.'images_unlinked.db' : DB.'media_unlinked.db';
 if(is_array($images_cache)){
  usort($images_cache, 'SORT_BY_DATE'); // from new to old
  rewrite($db, array_unique($images_cache), $add);
 }
 // make unliked & linked images database
 if($add && is_file($db)) $images_cache = file($db);
 if(!empty($images_cache)){
  foreach ($images_cache as $I){
   $parts = explode("\t", $I);
   if(strpos($parts[0], '|||')){
    $images_unlinked_cache[] = $I;
   } else $images_linked_cache[] = $I;
  }
 }
 $images_linked_cache = preg_replace('{^(\d{1,9})(\|.+$)}e', "sprintf('%010s', '$1').'$2'", $images_linked_cache);
 $images_unlinked_cache = preg_replace('{^(\d{1,9})(\|.+$)}e', "sprintf('%010s', '$1').'$2'", $images_unlinked_cache);
 usort($images_linked_cache, 'SORT_BY_DATE'); rewrite($db_linked, array_unique($images_linked_cache));
 usort($images_unlinked_cache, 'SORT_BY_DATE'); rewrite($db_unlinked, array_unique($images_unlinked_cache));
 if(is_file('feeds/gallery1.rss')) include_once('modules/mrss.inc.php');
 if(is_file('feeds/mrss.xml') && is_file('modules/mrss2.inc.php')) include_once('modules/mrss2.inc.php');
 unset($images_cache, $images_linked_cache, $images_unlinked_cache);
}

function get_links($content){
 preg_match_all('{<a.*?href=["\'](http://[^"\']+?)["\'][^>]*>}i', $content, $links);
 $links = array_unique($links[1]);
 if(!empty($links)){
  $_links = array();
  foreach($links as $link){
   $parts = parse_url($link);
   if($parts['path']=='' || $parts['path']=='/' || strstr($parts['path'], 'index')) continue;
   $_links[] = $link;
  }
  return $_links;
 } else return array();
}

function my_auto_discovery($uri){
 $page = file_get_contents($uri);
 preg_match_all("{(<rdf:RDF xmlns:rdf.*?</rdf:RDF>)}s", $page, $RDF);
 return preg_replace('/(.+)trackback:ping="(http:\/\/[^"]+)".*/s','$2',$RDF[1]);
}

function cast_ping_data($com='', $ping_target=''){
 global $_self, $back, $mb, $DIVISION;
 $uid = str_replace('d', '', $_REQUEST['UID']);
 $url = $uid=='' ? ROOT_PATH.'index.php' : ROOT_PATH.'index.php?UID='.$uid;
 $excerpt = $com != '' ? str_replace('`', '', $com) : p_('excerpt');
 $excerpt = strip_tags($excerpt);
 $excerpt = preg_replace(array('/\[style\].*\[\/style\]/is', "{\[g\](.*?)\[/g\]}"), array('', '$1'), $excerpt);
 $excerpt = my_substr($excerpt, 0, 100);
 if(trim($excerpt)=='') $excerpt = '＜トラックバックエントリー＞';
 $info = array(
   'entry'     => time(),
   'url'       => my_convert_encoding($url, 'utf-8', 'auto'),
   'title'     => my_convert_encoding($_REQUEST['title'], 'utf-8', 'auto'),
   'excerpt'   => my_convert_encoding($excerpt, 'utf-8', 'auto'),
   'blog_name' => my_convert_encoding($_REQUEST['blog_name'], 'utf-8', 'auto'),
   'ping_url'  => $_REQUEST['ping_url'],
   'top_url'   => $_REQUEST['top_url']
  );
 $info = MAGIC_QUOTES ? array_filter($info, "stripslashes") : $info;
 if(empty($info['url'])) $info['url'] = 'http://'.str_replace('admin.php', 'index.php', $_SERVER['REMOTE_ADDR']);
 $ping_url = !empty($info['ping_url']) ? parse_url($info['ping_url']) : parse_url($ping_target);
 if(p_('send_ping_auto')==1) $ping_url = parse_url($ping_target);
 $info['title'] = urlencode($info['title']);
 $info['blog_name'] = urlencode($info['blog_name']);
 $info['excerpt'] = urlencode($info['excerpt']);
 if(empty($ping_url)){
  return $DIVISION['header'] .= '<div class="alert">Ping-url is empty!<br />'.$back.'</div>';
 }
 $put_data = "url=".$info['url']."&title=".$info['title']."&blog_name=".$info['blog_name']."&excerpt=".$info['excerpt'];
 $query = isset($ping_url['query']) ? '?'.$ping_url['query'] : '';
 if(empty($ping_url)) return $DIVISION['body'] .= '<h4 class="center alert">トラックバック未送信</h4>'.NL;
 $response = tb_http($ping_url['host'], $ping_url['path'].$query, $put_data);
 if(!$response[0]){
  $DIVISION['body'] .= '<h4 class="center alert">'.$response[1].'</h4>'.NL;
  $DIVISION['body'] .= '<h4 class="center alert">トラックバックPing送信失敗！</h4>'.NL;
 } else {
  $DIVISION['body'] .= '<h4 class="center alert">トラックバックPing送信成功！</h4>'.NL;
 }
}

function tb_http($host, $path, $data, $debug=TRUE){
 $fp = @fsockopen($host, 80, $errno, $errstr, $timeout=5);
 if(!$fp){
  if($debug) @rewrite(OD.'debug.txt','Socket接続出来ませんでした。');
  return array(0, "相手のサーバーエラーです。");
 }
 if(stristr($host, 'exblog')){
  $data = my_convert_encoding($data, 'sjis', 'utf-8');
 }
 if(@socket_set_timeout($fp, $timeout)){
  $req = "POST $path HTTP/1.0\r\n";
  $req .= "Host: $host\r\n";
  $req .= "Content-Type: application/x-www-form-urlencoded\r\n";
  $req .= "User-Agent:ppBlogTrackBack\r\n";
  $req .= "Content-length: ". strlen($data) ."\r\n";
  $req .= "Connection: close\r\n\r\n";
  $req .= "$data\r\n";
  fputs($fp, $req);
  $res = "";
  while(!feof($fp)){
   $res .= @fgets($fp, 256);
  }
  fclose($fp);
  if(preg_match('{(?:Thanks |<error>0</error>)}is', $res)) return array(1, $res);
  if($debug) @rewrite(OD.'debug.txt',$req.NL.NL.$res, TRUE);
  return array(0, "指定されたトラックバックURIは無効かあるいは何かしらの送信エラーの可能性があります。");
 }
}

function tb_response($msg = "", $error = 0){
 header("Content-Type: text/xml\n\n");
 echo<<<__HTML
<?xml version="1.0" encoding="utf-8" ?>
<response>
<error>$error</error>
<message>$msg</message>
</response>
__HTML;
 exit;
}

function ping_form($ping_url='', $blog_name=BLOG_NAME, $top_url=ROOT_PATH, $sub=TRUE){
 global $_self, $DIVISION;
 $url = p_('UID')=='' ? ROOT_PATH.$_self : ROOT_PATH.$_self.'?UID='.p_('UID');
 if($sub==TRUE){
  $cap = '<div id="pingform" style="display:none;">'.NL;
  $title = '';
  $tail = '';
  $excerpt = '';
  $article_url = '';
 } else {
  $cap = '<div style="font:600 14px arial;margin:auto;width:550px;">
 <form method="post" action="trackback.php">
  <div class="hidden"><input type="hidden" name="mode" value="cast_ping" /></div>
 ';
  $title = '<tr>
     <td class="rt"><label for="ttl">Title</label>:</td>
     <td><input id="ttl" name="title" size="30" value="" /></td>
    </tr>
  ';
  $tail = '<p class="center"><input type="submit" value="submit" class="button" /></p>'.NL.'</form>'.NL;
  $excerpt = '<tr>
     <td class="rt"><label for="excerpt">記事概要:</label></td>
     <td><input id="excerpt" name="excerpt" size="30" maxlength="250" value="" /></td>
    </tr>
  ';
  $article_url = '<tr>
     <td class="rt"><label for="url">記事URL :</label></td>
     <td><input id="url" name="url" size="30" value="'.$url.'" /></td>
    </tr>'.NL;
 }
 $str =<<<__HTML
 $cap
   <table border="0" cellspacing="3" cellpadding="1" style="margin:auto;width:550px;font-size:100%;">
    <tr>
     <td class="right"><label for="ping_url">ping送信先URL:</label></td>
     <td class="left"><input id="ping_url" name="ping_url" size="30" onfocus='this.value=""' value="$ping_url" style="width:95%;" /></td>
    </tr>
    $title
    <tr>
     <td class="right"><label for="blog_name">blog名:</label></td>
     <td class="left"><input id="blog_name" name="blog_name" size="30" value="$blog_name" style="width:95%;" /></td>
    </tr>
    <tr>
     <td class="right"><label for="blog_name">blogトップURL:</label></td>
     <td class="left"><input id="top_url" name="top_url" size="30" value="$top_url" style="width:95%;" /></td>
    </tr>
    $excerpt
    $article_url
   </table>
 $tail
 </div>
__HTML;
 if($sub==FALSE){
  return $DIVISION['body'] .= '<h3>ppBlog::PingForm</h3>'.NL.$str;
 } else return $str;
}

function update_ARCHIVES($yyyymm='', $utime='', $fsize = 0, $backup=FALSE){
 global $LOGS, $MHT_LIST;
 if(!is_file($archives_ini=OD.'mht.ini.php') || count($MHT_LIST) < count($LOGS)){
  foreach($LOGS as $i=>$logs){
   if(!empty($MHT_LIST[$i])){
    list(,$created,) = explode('|', $MHT_LIST[$i]);
   } else $created = 0;
   $_count = count( my_file($logs,TRUE) );
   if($_count==0) continue;
   $MHT_LIST[] = str_replace(EXT, '', basename($logs)).'|'.(($created>0)?$created:0).'|'.filemtime($logs).'|'.$_count.'|'.$fsize.'|';
  }
  rewrite_ini($archives_ini, '', '$MHT_LIST');
 }
 include_once ($archives_ini);
 $match = FALSE;
 foreach ($MHT_LIST as $i=>$mht){
  list($date, $created, $lastmod,) = explode('|', $mht);
  if($yyyymm==$date){
   $match = TRUE;
   break;
  }
 }
 $log = LOG.$yyyymm.EXT;
 if(!$match){
  array_unshift($MHT_LIST, $yyyymm.'|'.($backup?time():0).'|'.filemtime($log).'|'.count(my_file($log, TRUE)).'|'.$fsize.'|');
 } else $MHT_LIST[$i] = $yyyymm.'|'.($utime==''?$created:$utime).'|'.filemtime($log).'|'.count(my_file($log, TRUE)).'|'.$fsize.'|';
 rewrite_ini($archives_ini, $MHT_LIST);
}

function update_MT($yyyymm='', $utime=''){
 global $LOGS, $MT_LIST;
 if(!is_file($mt_ini=OD.'mt.ini.php') || count($MT_LIST) < count($LOGS)){
  foreach($LOGS as $i=>$logs){
   $_count = count( my_file($logs, TRUE) );
   if($_count==0) continue;
   $MT_LIST[] = str_replace(EXT, '', basename($logs)).'|0|'.filemtime($logs).'|'.$_count.'|';
  }
  rewrite_ini($mt_ini, '', '$MT_LIST');
 }
 include_once ($mt_ini);
 $match = FALSE;
 foreach ($MT_LIST as $i=>$mt){
  list($date, $created, $lastmod,) = explode('|', $mt);
  if($yyyymm==$date){
   $match = TRUE;
   break;
  }
 }
 $log = LOG.$yyyymm.EXT;
 if(!$match){
  array_unshift($MT_LIST, $yyyymm.'|'.time().'|'.filemtime($log).'|'.count(my_file($log, TRUE)).'|');
 } else $MT_LIST[$i] = $yyyymm.'|'.($utime==''?$created:$utime).'|'.filemtime($log).'|'.count(my_file($log, TRUE)).'|';
 rewrite_ini($mt_ini, $MT_LIST);
}

function raw_($value=''){
 if($value=='') return '';
 return MAGIC_QUOTES ? stripslashes($_REQUEST[$value]) : $_REQUEST[$value];
}
?>
